{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`move` 语义是 C++11 起引入的一组语言与库特性，用于实现**资源所有权的高效转移**。它让编译器能够在对象从临时量或即将过期对象中“窃取”资源时，避免昂贵的拷贝，从而提升性能并改善库设计。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `move` 语义通过右值引用和库辅助工具（`std::move`、`std::forward` 等）实现资源的高效转移。\n",
    "- 它是现代 C++ 性能与设计的基石，与容器、智能指针、泛型算法、协程等特性紧密相连。\n",
    "- 随着后续标准演进，移动语义的默认支持与优化（如保证 RVO、ranges 概念）持续加强，是理解现代 C++ 的必修课。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 基础概念\n",
    "\n",
    "C++11 重新定义了表达式的值类别：\n",
    "\n",
    "| 分类    | 含义                   | 示例            |\n",
    "| ------- | ---------------------- | --------------- |\n",
    "| lvalue  | 有持久地址或名字的对象 | `int x; x = 5;` |\n",
    "| xvalue  | “将亡值”，资源可被重用 | `std::move(x)`  |\n",
    "| prvalue | 纯右值，多为临时对象   | `Foo()`         |\n",
    "\n",
    "“右值引用（`T&&`）”可以绑定到 xvalue/prvalue 上，为移动语义提供了语言基础。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  `move` 与移动特殊成员"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 移动构造函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "class Buffer {\n",
    "public:\n",
    "    Buffer(size_t n) : size_(n), data_(new int[n]) {}\n",
    "    ~Buffer() { delete[] data_; }\n",
    "\n",
    "    // 移动构造\n",
    "    Buffer(Buffer&& other) noexcept\n",
    "        : size_(other.size_), data_(other.data_) {\n",
    "        other.size_ = 0;\n",
    "        other.data_ = nullptr; // 避免析构时重复释放\n",
    "    }\n",
    "\n",
    "    // 禁止拷贝（演示用途）\n",
    "    Buffer(const Buffer&) = delete;\n",
    "    Buffer& operator=(const Buffer&) = delete;\n",
    "\n",
    "    // 移动赋值\n",
    "    Buffer& operator=(Buffer&& other) noexcept {\n",
    "        if (this != &other) {\n",
    "            delete[] data_;\n",
    "            size_ = other.size_;\n",
    "            data_ = other.data_;\n",
    "            other.size_ = 0;\n",
    "            other.data_ = nullptr;\n",
    "        }\n",
    "        return *this;\n",
    "    }\n",
    "\n",
    "private:\n",
    "    size_t size_;\n",
    "    int* data_;\n",
    "};"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `std::move` 的作用: `std::move` **不搬运任何东西**，它只是一个转换工具，将对象显式转换为 xvalue，从而触发移动构造或移动赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "Buffer buf1(1024);\n",
    "Buffer buf2 = std::move(buf1); // 调用移动构造"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "等价于："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "template<typename T>\n",
    "constexpr std::remove_reference_t<T>&& move(T&& t) noexcept {\n",
    "    return static_cast<std::remove_reference_t<T>&&>(t);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 为什么需要移动语义？\n",
    "\n",
    "1. **性能**：避免深拷贝，尤其是容器、字符串、智能指针等管理大量资源或堆内存的类型。\n",
    "2. **RAII 语义**：如 `std::unique_ptr` 等**唯一所有权**类型必须可转移而不可复制。\n",
    "3. **异常安全**：提供强保证／无抛出移动操作，支持异常安全的容器操作（如 `vector::push_back`）。\n",
    "4. **库设计**：提高泛型代码效率，使标准库容器和算法在处理临时对象时更高效。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实现细节与惯用法\n",
    "\n",
    "Rule of Five\n",
    "- 当你自定义资源管理类时，如果实现了析构/拷贝/赋值，就通常也要实现移动构造与移动赋值（或显式 `= default`/`= delete`）。\n",
    "\n",
    "`noexcept` 与移动\n",
    "- 多数移动特殊成员应标记为 `noexcept`。标准容器在满足移动操作 `noexcept` 时，会倾向于使用移动而非拷贝，从而避免回退到拷贝以维护强异常保证。\n",
    "\n",
    "使用 `std::exchange`\n",
    "- 简化移动赋值中的“偷资源→留空壳”逻辑：`value_ = std::exchange(other.value_, nullptr);`\n",
    "\n",
    "> `std::exchange` 是 C++14 引入的一个泛型函数模板，位于头文件 `<utility>` 中，常用于在一次操作中“交换并返回旧值”。它的典型应用是配合移动语义，将对象置于“默认状态”并取得旧对象内容，简化资源转移的代码。\n",
    "\n",
    "避免在操作完后的对象使用未定义状态\n",
    "- 移动后对象必须保持**有效但未指定状态**。保证可安全析构，也可赋值或重置，但其值内容不可假定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "class Buffer {\n",
    "public:\n",
    "    Buffer& operator=(Buffer&& other) noexcept {\n",
    "        if (this != &other) {\n",
    "            delete[] data_;\n",
    "            data_ = std::exchange(other.data_, nullptr); // 避免手动编写多行拆分赋值和重置代码，提高可读性与安全性\n",
    "            size_ = std::exchange(other.size_, 0);\n",
    "        }\n",
    "        return *this;\n",
    "    }\n",
    "\n",
    "private:\n",
    "    std::size_t size_{0};\n",
    "    int* data_{nullptr};\n",
    "};"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 与其他特性的联动\n",
    "\n",
    "| 特性/工具                                  | 关联说明                                                     |\n",
    "| ------------------------------------------ | ------------------------------------------------------------ |\n",
    "| **`std::forward`**                         | 完美转发中使用 `T&&`（转发引用）将参数保留原值类别，必要时配合 `std::move` 将转发对象变为右值。 |\n",
    "| **`std::move_if_noexcept`**                | 若移动可能抛异常则退化为拷贝，常用于强异常保证的容器操作。   |\n",
    "| **移动迭代器 (`std::move_iterator`)**      | 将普通迭代器转换为“移动迭代器”，算法在赋值时会调用移动赋值。 |\n",
    "| **智能指针**                               | `std::unique_ptr` 依赖移动语义；`std::shared_ptr` 虽可拷贝，但移动可减少引用计数更新。 |\n",
    "| **`std::function`、`std::async` 等库组件** | 转移可调用对象/任务，避免不必要的复制。                      |\n",
    "| **标准容器**                               | 如 `std::vector` 在扩容、插入临时值时自动利用移动；`std::map::insert` 将参数作为右值时避免额外构造。 |\n",
    "| **`constexpr`/`noexcept` 结合**            | 让移动操作在更多编译期或异常安全上下文可用。                 |\n",
    "| **类型 traits**                            | `std::is_move_constructible`, `std::is_move_assignable` 等帮助在泛型库中根据可移动性做重载或编译期决策。 |\n",
    "| **`auto` 与结构化绑定**                    | 搭配移动语义可减少拷贝（如 `auto str = std::move(s);`），结构化绑定默认按值 (prvalue) 解包也会触发移动或拷贝。 |\n",
    "| **`std::optional`、`std::variant`**        | 内部转移存储对象，移动语义让它们在保持异常安全的同时更高效。 |\n",
    "| **协程与 ranges（C++20+）**                | 大量依赖可移动对象，尤其是在生成器、任务类型中。             |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++11 之后的演进\n",
    "\n",
    "| 标准版本          | 语言层面的演进                                               | 标准库层面的增强                                             | 备注                                                 |\n",
    "| ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------------------- |\n",
    "| C++14             | 对右值引用与泛型编程的配合更成熟；更多默认 `noexcept` 传播至移动操作 | `std::make_unique` 等实用工厂函数出现，便于创建可移动、不可复制对象 | 虽无线性语义大改，但生态开始以移动语义为默认性能策略 |\n",
    "| C++17             | **强制返回值优化 (RVO)**，减少手写 `std::move`；临时物化规则更新，纯右值不再产生中间临时对象 | 新增 `std::optional`、`std::variant`、`std::any` 等类型，均要求高效移动；标准容器对移动构造、移动插入的 `noexcept` 约束更严格 | RVO 的保证使“返回局部对象”更高效、简单               |\n",
    "| C++20             | `concepts` 引入 `std::movable`、`std::movable` 等约束，明确泛型对移动能力的要求；协程框架广泛依赖可移动对象传递状态 | Ranges 库提供 `std::ranges::move` 等算法；`std::span`、`std::atomic` 等类型在移动语义下行为更明确 | 概念让移动语义成为范式约束的一部分                   |\n",
    "| C++23             | 引入 `std::expected`、`std::generator`（协程 TS 合并）等类型，继续强调移动/转移所有权 | `std::ranges` 体系完善，更多算法提供移动重载；标准库更全面标注 `constexpr`/`noexcept`，提升编译期与异常安全下的移动效率 | 对协程、ranges 生态的支撑依赖可移动性                |\n",
    "| C++26（草案方向） | 讨论基于值类别的进一步优化，例如对 `copy`/`move` 泛型算法的统一；`deducing this` 等提案增强链式调用中值类别保持 | 预计引入更多容器/工具类支持异步与协作场景，移动语义仍为核心  | 具体内容取决于最终草案，但趋势是“可移动”成为基本要求 |\n",
    "\n",
    "> **提示**：虽然各版本对移动语义本身的语法变化不大，但库与语言周边持续为“可移动”场景做优化，理解这些演进有助于在现代 C++ 中写出高效、安全的代码。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 常见陷阱与最佳实践\n",
    "\n",
    "1. **避免对对象重复 `std::move`**：对同一对象多次移动通常无意义，也可能导致逻辑错误。\n",
    "2. **不要移动临时对象返回值**：`return std::move(obj);` 在 C++17 起反而会抑制 RVO，除非需要显式转为不同类型或条件分支返回的值类别不一致。\n",
    "3. **对参数移动前先判断**：对函数参数（形参）调用 `std::move` 时应意识到参数是 lvalue；若你不再使用它，才移动。\n",
    "4. **copy-and-swap 与移动**：经典的 `copy-and-swap` 技法在移动语义下可以改造为 `move-and-swap`，但注意效率与异常保证。\n",
    "5. **接口设计**：接受参数时可以提供按值重载结合移动（“sink 参数”模式）：`void set_value(std::string value) { member_ = std::move(value); }`，调用方可以传 lvalue 或右值。\n",
    "6. **考虑 `noexcept`**：移动操作若可能抛异常，会让标准容器回退到拷贝，导致性能突然下降。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
